package jm.easyconfig;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Objects;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class CfgApplication {

	private static byte[] en_de_crypt(byte[] content, String password, int mode) throws Exception {
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
		random.setSeed(password.getBytes(StandardCharsets.UTF_8));
		kgen.init(128, random);
		SecretKey secretKey = kgen.generateKey();
		byte[] enCodeFormat = secretKey.getEncoded();
		SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");

		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(mode, key);
		byte[] result = cipher.doFinal(content);
		return result;
	}

	private static String cipherKey(String salt) {
		return "aA881bLwMhst6AmfBEkcJYu67VCrkbn1eIz3YyVZKdQ=" + salt;
	};

	static String encrypt(String content, String salt) {
		if (content == null)
			return null;

		try {
			byte[] en = en_de_crypt(content.getBytes(StandardCharsets.UTF_8), cipherKey(salt), Cipher.ENCRYPT_MODE);
			return Base64.getEncoder().encodeToString(en);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	static String decrypt(String content, String salt) {
		if (content == null)
			return null;

		try {
			byte[] de = Base64.getDecoder().decode(content);
			return new String(en_de_crypt(de, cipherKey(salt), Cipher.DECRYPT_MODE), StandardCharsets.UTF_8);
		} catch (Exception e) {
			// decrypt method is used for each item in loop. throw exception will break loop
			// except to add try catch block.
			CfgHelper.logger.error("Error to decrypt for {}, message:{}", content, e.getMessage());
		}

		return null;
	}

	public static void main(String[] args) throws Throwable {
		if (args.length < 2) {
			printPrompt(args);
			return;
		}

		String action = args[0].trim();
		String content = args[1].trim();

		String salt = "";
		if (args.length == 4 && Objects.equals("-salt", args[2])) {
			salt = args[3].trim();
		} else if (args.length == 3) {
			printPrompt(args);
			return;
		}

		String result = "";
		switch (action) {
		case "-encrypt":
			result = encrypt(content, salt);
			break;
		case "-decrypt":
			result = decrypt(content, salt);
			break;
		default:
			printPrompt(args);
		}

		System.out.println(result);
	}

	static void printPrompt(String[] args) {
		System.out.println("Just commands as below are supported.");

		String jarName = CfgApplication.class.getProtectionDomain().getCodeSource().getLocation().getFile();
		jarName = jarName.substring(jarName.lastIndexOf("/") + 1);

		System.out.println("java -jar " + jarName + " -encrypt yourPlainText -salt yourKey");
		System.out.println("java -jar " + jarName + " -decrypt yourCipherText -salt yourkey");
		System.out.println("java -jar " + jarName + " -encrypt yourPlainText");
		System.out.println("java -jar " + jarName + " -decrypt yourCipherText");
	}

}
